package dao

import (
	"github.com/pkg/errors"
	"github.com/spf13/cast"
	"nft-server/model"
	"nft-server/util"
)

type MetaDataDao struct {
	BaseDao
}

type IMetaDataDao interface {
	SaveMetaDataInfo(MetaData *model.MetaData) error
	GetMetaDataByCollectionIndexAndTokenId(collectionIndex, tokenId string) (*model.MetaData, error)
	GetMetaDataByCollections(userId int, collectionIndex []string) (metadata []*model.MetaData, size int, err error)
	GetMetaDataExact(userId int, collectionIndex string, subCollectionIndex []int) (metadata []*model.MetaData, size int, err error)
	GetMetaDataByIdentity(collectionIndex string, subCollectionIndex int) (metadata *model.MetaData, err error)
}

func GetMetaDataDao() IMetaDataDao {
	dao := &MetaDataDao{}
	dao.Init()
	return dao
}
func (cdd *MetaDataDao) SaveMetaDataInfo(MetaData *model.MetaData) error {
	_, err := cdd.O.Insert(MetaData)
	if err != nil {
		return errors.Errorf("insert error: %v", err)
	}
	return nil
}
func (cdd *MetaDataDao) GetMetaDataByIdentity(collectionIndex string, subCollectionIndex int) (*model.MetaData, error) {
	metadata := model.MetaData{}
	err := cdd.O.QueryTable(&model.MetaData{}).Filter("collection_index", collectionIndex).Filter("sub_collection_index", subCollectionIndex).One(&metadata)
	if err != nil {
		return nil, errors.Errorf("query table error: %v", err)
	}
	return &metadata, nil
}

//用集合ID和tokenID查找对应的metadata
func (cdd *MetaDataDao) GetMetaDataByCollectionIndexAndTokenId(collectionIndex, tokenId string) (*model.MetaData, error) {
	var MetaData []*model.MetaData
	_, err := cdd.O.QueryTable(&model.MetaData{}).Filter("collection_index", collectionIndex).Filter("start_token_id__lte", tokenId).All(&MetaData)
	if err != nil {
		return nil, errors.Errorf("query table error: %v", err)
	}
	var retData = new(model.MetaData)
	queryTokenId := cast.ToInt(tokenId)
	for _, oneMetadata := range MetaData {
		leftBound := cast.ToInt(oneMetadata.StartTokenID)
		rightBound := leftBound + cast.ToInt(oneMetadata.Amount)
		if leftBound <= queryTokenId && queryTokenId < rightBound {
			retData = oneMetadata
			break
		}
	}
	return retData, nil
}

//得到该用户底下指定集合(数组0的所有元数据，每个集合中可能包含多个元数据
func (cdd *MetaDataDao) GetMetaDataByCollections(userId int, collectionIndex []string) (metadata []*model.MetaData, size int, err error) {
	var MetaData []*model.MetaData
	recode := cdd.O.QueryTable(&model.MetaData{})
	if userId != util.InvalidNumber {
		recode = recode.Filter("user_id", userId)
	}
	if len(collectionIndex) != 0 {
		recode = recode.Filter("collection_index__in", collectionIndex)
	}
	_, err = recode.All(&MetaData)
	if err != nil {
		return nil, -1, errors.Errorf("query table error: %v", err)
	}
	size = len(MetaData)
	return MetaData, size, nil
}

//获取指定metaData
func (cdd *MetaDataDao) GetMetaDataExact(userId int, collectionIndex string, subCollectionIndex []int) (metadata []*model.MetaData, size int, err error) {
	var MetaData []*model.MetaData
	recode := cdd.O.QueryTable(&model.MetaData{})
	if userId != util.InvalidNumber {
		recode = recode.Filter("user_id", userId)
	}
	if len(collectionIndex) != 0 {
		recode = recode.Filter("collection_index", collectionIndex)
	}
	if len(subCollectionIndex) > 0 {
		recode = recode.Filter("sub_collection_index__in", subCollectionIndex)
	}
	_, err = recode.All(&MetaData)
	if err != nil {
		return nil, -1, errors.Errorf("query table error: %v", err)
	}
	size = len(MetaData)
	return MetaData, size, nil
}

func (cdd *MetaDataDao) UpdateMetaDataInfo(MetaData *model.MetaData) error {
	_, err := cdd.O.Update(MetaData)
	if err != nil {
		return errors.Errorf("update error: %v", err)
	}
	return nil
}
